﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<memory>
#include<functional>
#include<atomic>
using namespace std;
//struct Date
//{
//	int _year;
//	int _month;
//	int _day;
//
//	Date(int year = 1, int month = 1, int day = 1)
//		:_year(year)
//		, _month(month)
//		, _day(day)
//	{}
//
//	~Date()
//	{
//		cout << "~Date()" << endl;
//	}
//};

//int main()
//{
//	auto_ptr<Date> ap1(new Date);
//	// 拷贝时，管理权限转移，被拷贝对象ap1悬空
//	auto_ptr<Date> ap2(ap1);
//
//	// 空指针访问，ap1对象已经悬空
//	//ap1->_year++;
//
//	unique_ptr<Date> up1(new Date);
//	// 不支持拷贝
//	//unique_ptr<Date> up2(up1);
//
//	// 支持移动，但是移动后up1也悬空，所以使用移动要谨慎
//	//unique_ptr<Date> up3(move(up1));
//
//	shared_ptr<Date> sp1(new Date);
//	// 支持拷贝
//	shared_ptr<Date> sp2(sp1);
//	shared_ptr<Date> sp3(sp2);
//	cout << sp1.use_count() << endl;
//	sp1->_year++;
//	cout << sp1->_year << endl;
//	cout << sp2->_year << endl;
//	cout << sp3->_year << endl;
//
//	return 0;
//}


struct Date
{
	int _year;
	int _month;
	int _day;

	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

	~Date()
	{
		cout << "~Date()" << endl;
	}
};

namespace xc
{
	template<class T>
	class shared_ptr
	{
	public:
		shared_ptr(T* ptr)
			:_ptr(ptr)
			, _pcount(new int(1))
		{}
		template<class D>
		shared_ptr(T* ptr, D del)
			: _ptr(ptr)
			, _pcount(new int(1))
			, _del(del)
		{}
		~shared_ptr()
		{
			if (--(*_pcount) == 0)
			{
				//delete _ptr;
				_del(_ptr);
				delete _pcount;
			}
		}
		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			, _pcount(sp._pcount)
		{
			(*_pcount)++;
		}
		// sp1 = sp4;
		// sp4 = sp4;释放了自己在赋值但是sp4变成野指针了
		// sp1 = sp2;无用功减了再加回来
		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			//if()(this != &sp)这种方式检查不了sp1 = sp2;
			if (_ptr != sp._ptr)
			{
				if (--(*_pcount) == 0)
				{
					delete _ptr;
					delete _pcount;
				}
				_pcount = sp._pcount;
				_ptr = sp._ptr;
				++(*_pcount);
			}
			return *this;
		}
		T& operator* ()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
		int use_count()
		{
			return *_pcount;
		}
	private:
		T* _ptr;
		int* _pcount;
		//atomi<int>* _pocunt;
		function<void(T*)> _del = [](T* ptr) {delete ptr; };
	};
	
}

//int main()
//{
//    xc::shared_ptr<Date> sp1(new Date);
//    xc::shared_ptr<Date> sp2(sp1);
//    // 拷贝构造
//    xc::shared_ptr<Date> sp3 = sp2;
//
//    xc::shared_ptr<Date> sp4(new Date);
//
//    sp1->_year++;
//    sp3->_month++;
//
//    // 赋值拷贝
//    //sp1 = sp4;
//    sp4 = sp4;
//    sp1 = sp2;
//
//	return 0;
//}

class Fclose
{
public:
	void operator()(FILE* ptr)
	{
		std::cout << "fclose: " << ptr << std::endl;
		fclose(ptr);
	}
};
template<class T>
void DeleteArrayFunc(T* ptr)
{
	delete[] ptr;
}

//int main()
//{
//	std::shared_ptr<Date> sp1(new Date);
//	//特化
//	std::shared_ptr<Date[]> sp2(new Date[10]);
//
//	// 定制删除器 都可以，相对建议lambda
//    std::shared_ptr<Date> sp3(new Date[10], [](Date* ptr) {delete[] ptr; });
//	//std::shared_ptr<Date> sp3(new Date[5], DeleteArrayFunc<Date>);
//
//	std::shared_ptr<FILE> sp5(fopen("Test.cpp", "r"), Fclose());
//	shared_ptr<FILE>sp6(fopen("Test.cpp", "r"), [](FILE* ptr) {
//		fclose(ptr);
//		});
//
//	std::unique_ptr<Date>up1(new Date);
//	//std::unique_ptr<Date[]>up1(new Date[10]);
//	// 定制删除器 建议仿函数
//	std::unique_ptr<FILE, Fclose> up3(fopen("Test.cpp", "r"));
//
//	auto fcloseFunc = [](FILE* ptr) {fclose(ptr); };
//	std::unique_ptr<FILE, decltype(fcloseFunc)> up4(fopen("Test.cpp", "r"), fcloseFunc);
//
//	return 0;
//}

//int main()
//{
//	std::shared_ptr<Date>sp1(new Date(2025, 1, 27));
//	shared_ptr<Date>sp2 = make_shared<Date>(2025, 1, 27);
//	shared_ptr<Date> sp4;
//
//	//if (sp1.operator bool())如果为空返回false不为空返回true
//    if (sp1)
//        cout << "sp1 is not nullptr" << endl;
//
//    //if (!sp4)
//    if (!sp4.operator bool())
//        cout << "sp4 is nullptr" << endl;
//
//	//不支持这样写
//	/* shared_ptr<Date> sp5 = new Date(2024, 9, 11);
//    unique_ptr<Date> sp6 = new Date(2024, 9, 11); */
//
//	return 0;
//}


//struct ListNode
//{
//	int _data;
//
//	/*ListNode* _next;
//	ListNode* _prev;
//	std::shared_ptr<ListNode> _next;
//	std::shared_ptr<ListNode> _prev;*/
//
//	// 这里改成weak_ptr，当n1->_next = n2;绑定shared_ptr时
//	// 不增加n2的引用计数，不参与资源释放的管理，就不会形成循环引用了
//	std::weak_ptr<ListNode> _next;
//	std::weak_ptr<ListNode> _prev;
//
//	~ListNode()
//	{
//		cout << "~ListNode()" << endl;
//	}
//};
//
//int main()
//{
//    // 循环引用 -- 内存泄露
//    std::shared_ptr<ListNode> n1(new ListNode);
//    std::shared_ptr<ListNode> n2(new ListNode);
//
//    cout << n1.use_count() << endl;
//    cout << n2.use_count() << endl;
//
//    n1->_next = n2;
//    n2->_prev = n1;
//
//    cout << n1.use_count() << endl;
//    cout << n2.use_count() << endl;
//
//    return 0;
//}

int main()
{
    std::shared_ptr<string> sp1(new string("111111"));
    std::shared_ptr<string> sp2(sp1);

    std::weak_ptr<string> wp = sp1;
    cout << wp.expired() << endl;//返回true表示资源已经销毁，false表示资源还在
    cout << wp.use_count() << endl;//引用计数

    // sp1和sp2都指向了其他资源，则weak_ptr就过期了
    sp1 = make_shared<string>("222222");
    cout << wp.expired() << endl;
    cout << wp.use_count() << endl;

    sp2 = make_shared<string>("333333");
    cout << wp.expired() << endl;
    cout << wp.use_count() << endl;

    wp = sp1;
    //std::shared_ptr<string> sp3 = wp.lock();
    auto sp3 = wp.lock();
    cout << wp.expired() << endl;
    cout << wp.use_count() << endl;
    sp1 = make_shared<string>("4444444");

    cout << wp.expired() << endl;
    cout << wp.use_count() << endl;

    return 0;
}


//int main()
//{
//    std::shared_ptr<string> sp1(new string("111111"));
//    std::shared_ptr<string> sp2(sp1);
//
//    std::weak_ptr<string> wp = sp1;
//    cout << wp.expired() << endl;
//    cout << wp.use_count() << endl;
//
//    // sp1和sp2都指向了其他资源，则weak_ptr就过期了
//    sp1 = make_shared<string>("222222");
//    cout << wp.expired() << endl;
//    cout << wp.use_count() << endl;
//
//    sp2 = make_shared<string>("333333");
//    cout << wp.expired() << endl;
//    cout << wp.use_count() << endl;
//
//    wp = sp1;
//    //std::shared_ptr<string> sp3 = wp.lock();
//    auto sp3 = wp.lock();
//    cout << wp.expired() << endl;
//    cout << wp.use_count() << endl;
//    sp1 = make_shared<string>("4444444");
//
//    cout << wp.expired() << endl;
//    cout << wp.use_count() << endl;
//
//    return 0;
//}